package org.jsola.hr.provider.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.FileItem;
import org.jsola.common.FileKit;
import org.jsola.common.SafeKit;
import org.jsola.exception.ParamException;
import org.jsola.file.common.Zip4jKit;
import org.jsola.file.core.FileProperties;
import org.jsola.file.entity.FileVersionDO;
import org.jsola.file.exception.FileException;
import org.jsola.file.service.IGeneralFileService;
import org.jsola.file.service.IOCRService;
import org.jsola.file.service.ISiteFileService;
import org.jsola.file.vo.BankCardInfoVO;
import org.jsola.hr.common.FileDown;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.UploadFileKit;
import org.jsola.hr.provider.IFileProviderService;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author zxy
 */
@Service("hrFileProviderServiceImpl")
@Slf4j
public class FileProviderServiceImpl implements IFileProviderService {


    @Autowired
    private ISiteFileService siteFileService;

    @Autowired
    private IGeneralFileService generalFileService;

    @Autowired
    private FileProperties fileProperties;

    @Autowired
    private IOCRService ocrService;

    @Override
    public FileVersionDO download(List<String> siteFileUrls, String zipName, Map<String, String> signNoIdCardMap, TokenUser tokenUser) {
        // 要下载的合同文件路径
        FileVersionDO fileVersionDO = siteFileService.download(siteFileUrls, zipName, tokenUser);
        File file = new File(fileVersionDO.getTempFilePath());
        ParamException.notNull(file, "下载文件失败，请联系管理员");
        String fileName = file.getName();
        if (!fileName.endsWith(".zip")) {
            // 非压缩包 直接更换名称
            String name = signNoToIdCard(signNoIdCardMap, fileVersionDO.getName(), 0);
            ParamException.hasLength(name, "未找到匹配的员工身份信息，请核对员工信息");
            fileVersionDO.setName(name);
            return fileVersionDO;
        }
        // 若是压缩包 解压到当前文件夹
        String path = file.getAbsolutePath().replace(fileName, "");
        Zip4jKit.extractAll(file, path);
        // 当前文件夹下所有文件
        File pathFile = new File(path);
        File[] tempList = pathFile.listFiles();
        ParamException.isFalse(tempList == null, "读取文件失败，请稍后再试");
        File dirFile = null;
        for (File file1 : tempList) {
            if (file1.isDirectory() && zipName.equals(file1.getName())) {
                dirFile = file1;
                break;
            }
        }
        ParamException.notNull(dirFile, "解压失败，请稍后再试");
        File[] files = dirFile.listFiles();
        ParamException.notNull(files, "解压失败，请稍后再试");
        String dirPath = path + zipName;
        for (int i = 0; i < files.length; i++) {
            String name = signNoToIdCard(signNoIdCardMap, files[i].getName(), i);
            ParamException.hasLength(name, "未找到匹配的员工身份信息，请核对员工信息");
            files[i].renameTo(new File(dirPath + File.separatorChar + name));
        }
        String zipFileName = zipName + ".zip";
        String outFile = dirPath + File.separatorChar + zipFileName;
        // 改名好的文件压缩
        Zip4jKit.compressFolder(outFile, dirPath);
        FileVersionDO zipFile = new FileVersionDO();
        zipFile.setExt("zip");
        zipFile.setName(zipFileName);
        zipFile.setTempFilePath(outFile);
        log.info("重新压缩的文件：{}", zipFile.toString());
        return zipFile;
    }


    /**
     * 签署编号转身份证
     *
     * @param signNoIdCardMap 签署编号-身份证
     * @param fileName        文件名
     * @param i               第几个文件
     * @return 身份证
     */
    public static String signNoToIdCard(Map<String, String> signNoIdCardMap, String fileName, int i) {
        for (String signNoId : signNoIdCardMap.keySet()) {
            if (fileName.contains(signNoId)) {
                String idCard = signNoIdCardMap.get(signNoId);
                if (idCard == null) {
                    idCard = "身份证号未填写";
                    if (i > 0) {
                        idCard += "(" + i + ")";
                    }
                }
                return fileName.replace(signNoId, idCard);
            }
        }
        // 没有匹配到签署编号 则不替换
        return fileName;
    }

    @Override
    public List<String> generalUpload(List<MultipartFile> files, String downloadType) {
        ParamException.notEmpty(files, "上传文件不能为空");
        List<String> tempFilePaths = new ArrayList<>();
        for (MultipartFile file : files) {
            // 先本地落盘
            String tempFilePath = FileKit.saveFileToLocal(file, fileProperties.getTempPath(), "upload", null, null);
            tempFilePaths.add(tempFilePath);
        }
        List<String> list = generalFileService.upload(tempFilePaths, downloadType);
        // 删除临时文件
        for (String tempFilePath : tempFilePaths) {
            boolean flg = new File(tempFilePath).delete();
        }
        return list;
    }

    @Override
    public List<String> siteUpload(List<MultipartFile> files, String downloadType, TokenUser tokenUser) {
        ParamException.notEmpty(files, "上传文件不能为空");
        MultipartFile[] multipartFiles = files.toArray(new MultipartFile[0]);
        return siteFileService.upload(multipartFiles, downloadType, tokenUser);
    }

    @Override
    public List<String> generalUpload(MultipartFile multipartFile, String downloadType) {
        return generalUpload(Collections.singletonList(multipartFile), downloadType);
    }

    @Override
    public List<String> generalUpload(File file, String downloadType) {
        FileItem fileItem = UploadFileKit.createFileItem(file);
        return generalUpload(new CommonsMultipartFile(fileItem), downloadType);
    }

    @Override
    public String siteUpload(File file, String downloadType, TokenUser tokenUser) {
        return siteFileService.upload(file, downloadType, tokenUser);
    }

    @Override
    public List<String> batchSiteUpload(List<File> fileList, String downloadType, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(fileList)) {
            return new ArrayList<>();
        }
        File[] files = fileList.toArray(new File[0]);
        return siteFileService.upload(files, downloadType, tokenUser);
    }

    @Override
    public List<String> uploadAndSetName(MultipartFile[] files, String downloadTyp, String fileNames, TokenUser tokenUser) {
        return siteFileService.uploadAndSetName(files, downloadTyp, fileNames, tokenUser);
    }

    @Override
    public BankCardInfoVO bankcard(MultipartFile file) {
        return ocrService.bankcard(file);
    }

    @Override
    public BankCardInfoVO bankcard(String bankCardImg, TokenUser tokenUser) {
        File file = urlToFile(bankCardImg, tokenUser);
        FileItem fileItem = createFileItem(file);
        MultipartFile commonsMultipartFile = new CommonsMultipartFile(fileItem);
        return ocrService.bankcard(commonsMultipartFile);
    }


    /**
     * url转File
     */
    private File urlToFile(String url, TokenUser tokenUser) {
        String[] split = url.split("/");
        // 根据“/”分割的倒数第二段
        String fileId = split[split.length - 2];
        Long aLong = SafeKit.getLong(fileId);
        String filePath;
        // 无法解析为长整数则视为网络图片
        if (aLong == null) {
            filePath = FileDown.getFilePath(url);
        } else {
            FileVersionDO fileVersionDO = siteFileService.download(url, tokenUser);
            HrException.notNull(fileVersionDO, "图片文件不存在");
            filePath = fileVersionDO.getTempFilePath();
        }
        FileSystemResource resource = new FileSystemResource(filePath);
        if (!resource.exists()) {
            throw new FileException("系统错误，文件不存在或已被删除");
        }
        return resource.getFile();
    }

    /**
     * File 转 FileItem
     */
    public static FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

}
